use crate::config::Config;
use markdown::{mdast::Node, ParseOptions};
use std::fs;
use std::path::{Path, PathBuf};

#[derive(Debug, Clone)]
pub struct RawCodeSnippet {
    pub tag: String,        // First line of code block, used for search
    pub code: String,       // Actual code to be executed
    pub language: String,   // Language identifier of the code block
    pub file_path: PathBuf, // Path to the file
    pub line_number: usize, // Starting line number of the code block in the file
    pub end_line: usize,    // Ending line number of the code block in the file
}

// Parse all code snippets from a single Markdown file (no ID assigned)
pub fn parse_snippets_from_file(
    path: &Path,
    config: &Config,
) -> Result<Vec<RawCodeSnippet>, Box<dyn std::error::Error>> {
    let content = fs::read_to_string(path)?;
    let ast =
        markdown::to_mdast(&content, &ParseOptions::default()).map_err(|e| format!("{:?}", e))?;

    let mut snippets = Vec::new();
    let mut current_line = 1;

    if let Some(children) = ast.children() {
        for node in children {
            if let Some(position) = node.position() {
                current_line = position.start.line;
            }

            if let Node::Code(code_block) = node {
                let lang = code_block.lang.clone().unwrap_or_else(|| "unknown".into());

                // Only process language types that exist in the configuration file
                if !config.languages.contains_key(&lang) {
                    continue;
                }

                let mut lines = code_block.value.lines();

                if let Some(first_line) = lines.next() {
                    let tag = first_line.trim();
                    let code = code_block.value.clone();

                    // Calculate end line: start line + number of lines in code + 1 (for closing ```)
                    let code_lines = code_block.value.lines().count();
                    let end_line = current_line + code_lines + 1; // +1 for closing ```

                    snippets.push(RawCodeSnippet {
                        tag: tag.to_string(),
                        code,
                        language: lang,
                        file_path: path.to_path_buf(),
                        line_number: current_line,
                        end_line,
                    });
                }
            }
        }
    }

    Ok(snippets)
}
